package com.start.security;


import com.start.common.constant.StartConstant;
import com.start.security.handler.UserNoAccessHandler;
import com.start.security.handler.UserUnauthorizedHandler;
import com.start.security.providers.ManagerAuthenticationProvider;
import com.start.security.providers.UserAuthenticationProvider;
import com.start.security.service.StartSecurityService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import java.util.List;

@Slf4j
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class StartSecurityConfig {

    /**
     * 用户token 加载器
     */
    @Autowired
    private StartTokenAuthenticationFilter startTokenAuthenticationFilter;
    /**
     * 用户无权限
     */
    @Autowired
    private UserNoAccessHandler noAccessHandler;
    /**
     * 用户验证失败
     */
    @Autowired
    private UserUnauthorizedHandler userUnauthorizedHandler;


    @Autowired
    private UserDetailsService userDetailsService;


    @Autowired
    private UserAuthenticationProvider userAuthenticationProvider;

    @Autowired
    private ManagerAuthenticationProvider managerAuthenticationProvider;


    private final StartSecurityService startSecurityService;

    public StartSecurityConfig(StartSecurityService startSecurityService) {
        this.startSecurityService = startSecurityService;
    }

    /**
     * 向AuthenticationManager添加Provider
     *
     * @return
     */
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(userAuthenticationProvider);
        auth.authenticationProvider(managerAuthenticationProvider);
    }


    @Autowired
    public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder.userDetailsService(this.userDetailsService).passwordEncoder(StartConstant.passwordEncoder);
    }


    @Bean
    @Order(0)
    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {

        http.httpBasic(AbstractHttpConfigurer::disable);
        http.cors(AbstractHttpConfigurer::disable);
        http.csrf(AbstractHttpConfigurer::disable);
        http.sessionManagement(e -> {
            e.disable();
            e.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        });

        http.formLogin(AbstractHttpConfigurer::disable);
        http.logout(AbstractHttpConfigurer::disable);
        http.addFilterBefore(startTokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
//        http.exceptionHandling(exceptionHandlingConfigurer -> exceptionHandlingConfigurer.authenticationEntryPoint(userUnauthorizedHandler).accessDeniedHandler(noAccessHandler));

        http.authorizeHttpRequests(e -> {
            e.requestMatchers(new AntPathRequestMatcher("/**", HttpMethod.OPTIONS.name())).permitAll();
            List<String> ignoreAuthUrl = startSecurityService.getIgnoreAuthUrl();
            System.out.println("不等登录可访问地址：");
            for (String url : ignoreAuthUrl) {
                e.requestMatchers(new AntPathRequestMatcher(url)).permitAll();
                System.out.println(url);
            }
            e.anyRequest().authenticated();
        });
        return http.build();
    }


}
